package com.example.fakeflappybird;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.text.Editable;
import android.util.AttributeSet;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;

import java.util.ArrayList;
import java.util.List;

public class FakeGameView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
    private int fakeViewWidth,fakeViewHeight;
    private SurfaceHolder surfaceHolder;
    private Bitmap btbkday,btbknight,btbird1,btbird2,btbird3,btground,btpipe,btrealbkground;
    private Bitmap btheader,bttile,bttips,btcard,btrestart,btpause,btreset;
    private Bitmap btsmall,btslow,btnum;
    private Bitmap btmutekibird1,btmutekibird2,btmutekibird3;
    private boolean switchdraw=true;
    private BitCore realbkground;
    private BitCore realbird;
    private BitCore[] realgrounds;
    private List<BitCore> realpipes;
    private Canvas canvas;
    private int pipedis=120;
    public static final int GAME_START=2016;
    public static final int GAME_STOP=2017;
    public static final int GAME_READY=2018;
    public static final int GAME_OVER=2019;
    private int gameStatus;
    private GameListener gameListener=null;
    public GameListener getGameListener() {
        return gameListener;
    }
    private boolean isflagRestart=false;
    private int cooldownmuteki=2560;
    private int cooldownmini=1024;
    public void setGameListener(GameListener gameListener) {
        this.gameListener = gameListener;
    }
    public void gamepause(){
        gameStatus=GAME_STOP;
    }
    public void gamestandingby(){
        gameStatus=GAME_READY;
    }
    public FakeGameView(Context context) {
        super(context);
        initFakeGameView(context);
    }

    public FakeGameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initFakeGameView(context);
    }

    public FakeGameView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initFakeGameView(context);
    }

    public FakeGameView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initFakeGameView(context);
    }
    private void initFakeGameView(Context context) {
        btbkday= BitmapFactory.decodeResource(context.getResources(),R.drawable.bkday);
        btbknight=BitmapFactory.decodeResource(context.getResources(),R.drawable.bknight);
        btbird1=BitmapFactory.decodeResource(context.getResources(),R.drawable.bird1);
        btbird2=BitmapFactory.decodeResource(context.getResources(),R.drawable.bird2);
        btbird3=BitmapFactory.decodeResource(context.getResources(),R.drawable.bird3);
        btmutekibird1=BitmapFactory.decodeResource(context.getResources(),R.drawable.mutekibird1);
        btmutekibird2=BitmapFactory.decodeResource(context.getResources(),R.drawable.mutekibird2);
        btmutekibird3=BitmapFactory.decodeResource(context.getResources(),R.drawable.mutekibird3);
        btpipe=BitmapFactory.decodeResource(context.getResources(),R.drawable.pipe);
        btground=BitmapFactory.decodeResource(context.getResources(),R.drawable.ground);
        btheader=BitmapFactory.decodeResource(context.getResources(),R.drawable.header);
        bttile=BitmapFactory.decodeResource(context.getResources(),R.drawable.title);
        bttips=BitmapFactory.decodeResource(context.getResources(),R.drawable.tips);
        btheader=getTransBitmap(btheader,birdsize,birdsize);
        surfaceHolder=getHolder();
        surfaceHolder.addCallback(this);
    }
    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
    initFakeGameData();
    }
    float birdsize=(float)(0.8);
    private void initFakeGameData(){
        gameStatus=GAME_READY;
    fakeViewWidth=getMeasuredWidth();
    fakeViewHeight=getMeasuredHeight();
    btrealbkground=getTransBitmap(btbkday,(float) fakeViewWidth/btbkday.getWidth(),(float) fakeViewHeight/btbkday.getHeight());
    btbird1=getTransBitmap(btbird1,birdsize,birdsize);
    btbird2=getTransBitmap(btbird2,birdsize,birdsize);
    btbird3=getTransBitmap(btbird3,birdsize,birdsize);
        btmutekibird1=getTransBitmap(btmutekibird1,birdsize,birdsize);
        btmutekibird2=getTransBitmap(btmutekibird2,birdsize,birdsize);
        btmutekibird3=getTransBitmap(btmutekibird3,birdsize,birdsize);
    btground=getTransBitmap(btground,(float) fakeViewWidth/btground.getWidth(),1);
    realbkground=new BitCore(btrealbkground,0,0,btrealbkground.getWidth(),btrealbkground.getHeight());
    realbird=new BitCore(btbird1,fakeViewWidth/2-btbird1.getWidth()/2,fakeViewHeight/2-btbird1.getHeight()/2,btbird1.getWidth(),btbird1.getHeight());
    realgrounds=createRealGround();
    realpipes=new ArrayList<>();
    pipedis=8*realbird.getH();
    new Thread(this).start();
    }
    public void gamerestart(){
        birdSpinRec=0;
        realbird.setX(fakeViewWidth/2-btbird1.getWidth()/2);
        realbird.setY(fakeViewHeight/2);
        isFall=false;
        createpipestime=0;
        realpipes=new ArrayList<>();
        changeTime=0;
        gameStatus=GAME_READY;
        isflagRestart=false;
        score=0;
        miniTime=0;
        mutekiTime=0;
        cooldownmuteki=2560;
        cooldownmini=1024;
        if (gameListener!=null)
        {
            gameListener.renewButtonHyperMuteki();
            gameListener.renewButtonMuteki();
        }
    }
    private BitCore[] createRealGround(){
        BitCore bitCoreStart=new BitCore(btground,0,fakeViewHeight-btground.getHeight(),btground.getWidth(),btground.getWidth());
        BitCore bitCoreEnd=new BitCore(btground,bitCoreStart.getX()+bitCoreStart.getW(),fakeViewHeight-btground.getHeight(),btground.getWidth(),btground.getWidth());
        return new BitCore[]{bitCoreStart,bitCoreEnd};
    }
    public Bitmap getTransBitmap(Bitmap bitmap,float dx,float dy){
    return Bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*dx),(int)(bitmap.getHeight()*dy),true);
    }
    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

    }

    @Override
    public void run() {
    while(switchdraw){
        drawUI();
    }
    }
    private void drawbkUI(){
    canvas.drawBitmap(realbkground.getBitmap(),realbkground.getX(),realbkground.getY(),null);
    }
    int birdSpinRec=0;
    private void drawbirdUI(){
        Matrix matrix=new Matrix();
        matrix.setTranslate(realbird.getX(),realbird.getY());
        matrix.postRotate(birdSpinRec,realbird.getX()+realbird.getW()/2,realbird.getY()+realbird.getH()/2);
        canvas.drawBitmap(realbird.getBitmap(),matrix,null);
    }
    private int birdSwitch=1;
    private int changeTime=0;
    private boolean isFall=true;
    private int timecount=0;
    private int fallv=0;
    private int jumpbeginTime=0;
    private int jumpTime=20;
    private int jumpv=8;
    private float acc=(float) 0.125;
    private float jumpvm;
    private int mutekiTime=0;
    public void mutekibird(){
        mutekiTime=256;
        cooldownmuteki=2560;
    }
    private int miniTime=0;
    public void minibird(){
        miniTime=512;
        cooldownmini=1024;
    }
    private void birdfall(){
    if(isFall){
            jumpvm=jumpv=10;
            birdSpinRec=45;
            realbird.setY(realbird.getY()+(fallv++));
    }else
    {
        if(jumpTime-jumpbeginTime>=0)
        {
            birdSpinRec=-45;
            realbird.setY(realbird.getY()-jumpv);
            jumpvm+=acc;
            jumpv=(int)jumpvm;
            jumpbeginTime++;
        }else{
            isFall=true;
            jumpbeginTime=0;
            fallv=0;
        }
    }
    }
    @Override
    public boolean onTouchEvent(MotionEvent event){
    switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            if(gameStatus==GAME_READY){
                gameStatus=GAME_START;
            }else if(gameStatus==GAME_START)
            {
            isFall=false;
            jumpbeginTime=0;
            }
            break;
    }
    return super.onTouchEvent(event);
    }
    private void birdchange(){
        changeTime++;
    if(changeTime>=10){
        if(mutekiTime>0){
            switch (birdSwitch){
                case 1:realbird.setBitmap(btmutekibird1);break;
                case 2:realbird.setBitmap(btmutekibird2);break;
                case 3:realbird.setBitmap(btmutekibird3);break;
            }
        }
        else
        {
            switch (birdSwitch){
                case 1:realbird.setBitmap(btbird1);break;
                case 2:realbird.setBitmap(btbird2);break;
                case 3:realbird.setBitmap(btbird3);break;
            }
        }
        changeTime=0;
        birdSwitch=birdSwitch==3?1:birdSwitch+1;
    }
    }
    int xv=6;
    private void changeground(){
    if(realgrounds[0].getX()+realgrounds[0].getW()>0){
        realgrounds[0].setX(realgrounds[0].getX()-xv);
    }else{
        realgrounds[0].setX(realgrounds[1].getX()+realgrounds[1].getW()-20);
    }
        if(realgrounds[1].getX()+realgrounds[1].getW()>0){
            realgrounds[1].setX(realgrounds[1].getX()-xv);
        }else{
            realgrounds[1].setX(realgrounds[0].getX()+realgrounds[0].getW()-20);
        }
    }
    private void drawgroundUI(){
    canvas.drawBitmap(realgrounds[0].getBitmap(),realgrounds[0].getX(),realgrounds[0].getY(),null);
        canvas.drawBitmap(realgrounds[1].getBitmap(),realgrounds[1].getX(),realgrounds[1].getY(),null);
    }
    private void drawpipes(){
    for(BitCore bitcore:realpipes){
        canvas.drawBitmap(bitcore.getBitmap(),bitcore.getX(),bitcore.getY(),null);
    }
    }
    private int score=0;
    private void changepipes(){
        List<BitCore> toRemove=new ArrayList<>();
    for(BitCore bitCore:realpipes){
        bitCore.setX(bitCore.getX()-xv);
        if(bitCore.getX()+bitCore.getW()+50<0)
            toRemove.add(bitCore);
        if(!bitCore.isHasbeenScored()&&bitCore.getX()+bitCore.getW()/2<realbird.getX())
        {
            score++;
            bitCore.setHasbeenScored(true);
        }
    }
    if(gameListener!=null)
        gameListener.addscore(score/2);
    realpipes.removeAll(toRemove);
    }
    int createpipestime=0;
    int between=100;
    private void createpipes(){
    createpipestime++;
    pipedis=(Math.abs((int)(Math.random()%4))+5)*realbird.getW();
    if(createpipestime>=between){
        createpipestime=0;
        int ranH=100+(int)(Math.random()*(realgrounds[0].getY()-pipedis-100));
        BitCore btcore=new BitCore(generatenewpipe(ranH,true),fakeViewWidth+50,0,realbird.getW()*2,ranH);
        Bitmap btmap=generatenewpipe(realgrounds[0].getY()-pipedis-btcore.getH(),false);
        BitCore bitCoreNeo=new BitCore(btmap,fakeViewWidth+50,btcore.getH()+pipedis,realbird.getW()*2,btmap.getHeight());
        realpipes.add(btcore);
        realpipes.add(bitCoreNeo);
    }
    }
    private Bitmap generatenewpipe(int h,boolean isRotat){
    Bitmap bitmap=Bitmap.createBitmap(realbird.getW()*2,h,Bitmap.Config.ARGB_8888);
    Canvas canvas=new Canvas(bitmap);
    if(isRotat){
        Matrix matrix=new Matrix();
        matrix.setRotate(180,realbird.getW()*2/2,h/2);
        canvas.setMatrix(matrix);
    }
    Bitmap pipebody=getTransBitmap(btpipe,(float) (realbird.getW()*2-35)/btpipe.getWidth(),(float) h/btpipe.getHeight());
    Matrix matrixNeo=new Matrix();
    matrixNeo.setTranslate(15,0);
    canvas.drawBitmap(pipebody,matrixNeo,null);
    Bitmap pipeheader=getTransBitmap(btheader,(float) realbird.getW()*2/btheader.getWidth(),(float) realbird.getH()/btheader.getHeight());
    canvas.drawBitmap(pipeheader,new Matrix(),null);
    return bitmap;
    }
    BitCore collidepipe;
    private void checkGameOver(){
        if(mutekiTime>0)
            return;
        if (realbird.getY()+realbird.getH()>=realgrounds[0].getY())
            gameStatus=GAME_OVER;
        else {
            for(BitCore bitcore:realpipes){
                if(ifcollide(realbird.getX(),realbird.getY(),realbird.getW(),realbird.getH(),bitcore.getX(),bitcore.getY(),bitcore.getW(),bitcore.getH()))
                {
                    gameStatus=GAME_OVER;
                    collidepipe=bitcore;
                    break;
                }
            }
        }
    }
    private boolean ifcollide(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
        if(x1<x2&&x1+w1<x2)
            return false;
        if(x2<x1&&x2+w2<x1)
            return false;
        if(y1<y2&&y1+h1<y2)
            return false;
        if(y2<y1&&y2+h2<y1)
            return false;
        return true;
    }

    public int getCooldownmuteki() {
        return cooldownmuteki;
    }

    public int getCooldownmini() {
        return cooldownmini;
    }

    public float getAcc() {
        return acc;
    }

    private void drawUI(){
    canvas=surfaceHolder.lockCanvas();
        if(miniTime>0){
        xv=3;
        between=250;
        }
        else{
            xv=6+score/10;
            if(between>realbird.getW()*2)
                between=100-score/10*10;
        }
    if(gameStatus==GAME_READY){
        birdchange();
        changeground();
    }
    if(gameStatus==GAME_START) {
        birdchange();
        birdfall();
        changeground();
        createpipes();
        changepipes();
    }
    drawbkUI();
    drawbirdUI();
    drawgroundUI();
    drawpipes();
    if(gameStatus==GAME_READY){
        canvas.drawBitmap(bttile,realbird.getX()+realbird.getW()/2-bttile.getWidth()/2,realbird.getY()-2*bttile.getHeight()-2*bttips.getHeight(),null);
        canvas.drawBitmap(bttips,realbird.getX()+realbird.getW()/2-bttips.getWidth()/2,realbird.getY()-bttile.getHeight()-bttips.getHeight(),null);
    }
    checkGameOver();
    if(cooldownmuteki>0){
        cooldownmuteki--;
    }else{
        if(gameListener!=null)
        gameListener.renewButtonHyperMuteki();
    }
    if(cooldownmini>0)
        cooldownmini--;
    else
    {
        if(gameListener!=null)
        gameListener.renewButtonMuteki();
    }
        if(mutekiTime>0){
            mutekiTime--;
        }
        if(miniTime>0){
            miniTime--;
        }
    if(gameStatus==GAME_OVER&&!isflagRestart){
        if(gameListener!=null)
        {
            isflagRestart=true;
            gameListener.gameover();
        }
    }
    surfaceHolder.unlockCanvasAndPost(canvas);
    }
}
